#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <fcntl.h>
#include <strings.h>


int size = sizeof(struct  sockaddr_in);
int connect_addr[20] ={0};   //设置数组存放已连接套接字
int num = 0;                //数组下标
    

int main(int argc, char const *argv[])
{
    //买手机（创建网络编口）
    int sockfd = socket(AF_INET , SOCK_STREAM , 0);

    //电话卡（设置IP信息以及端口号）
    // struct sockaddr_in {
    // sa_family_t     sin_family;     /* AF_INET */
    // in_port_t       sin_port;       /* Port number */
    // struct in_addr  sin_addr;       /* IPv4 address */
    // };

    struct  sockaddr_in  my_addr = {0};
    my_addr.sin_family =  AF_INET ;
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    my_addr.sin_port = htons(65002);

    //绑定手机和电话卡
     int ret =  bind(sockfd, (struct sockaddr *)&my_addr,size);
     if(ret)
     {
        perror("bind fail\n");
        return -1;
     }
     else
     {
        printf("bind success\n");
     }


    //设置监听
    if(listen(sockfd, 16)) //实际最大可以接受16+4=20个客户端
    {
        perror("listen fail\n");
        return -1;
    }
    else
    {
        printf("listen success\n");
    }

    //将监听字节字设置为非阻塞状态->如果不设置的话，监听会阻塞
    int state =  fcntl(sockfd,  F_GETFL, 0 );//获取sockfd的旗标
    state |= O_NONBLOCK; //将旗标社设置为非阻塞状态
    fcntl(sockfd, F_SETFL,state);// 把设置好的旗标放回去

    //等待连接
    char * recv_msg = calloc(1,128);
    struct  sockaddr_in  form_addr; //由于前面的监听套接字已经被设置为非阻塞，所以等待连接时失败会返回错误号码，成功会返回0
    while(1)
    {
        
        int connect_fd =  accept( sockfd, (struct sockaddr *)&form_addr, &size ); //如果成功会返回一个新的套接字
        //如果有客户端连接并且客户端没有满才继续
        if(connect_fd  > 0 && num < 20)//大于0意味着有客户端连接，一般是从3开始，1意味着标准输入，2是标准输出
        {
            //将连接套接字设置为非阻塞->不然如果这里不设置的话，程序也会在accept阻塞，所以要设置两次非阻塞；
            int state = fcntl(connect_fd , F_GETFL , 0);
            state |= O_NONBLOCK;
            fcntl(connect_fd , F_SETFL , state);

            connect_addr[num] = connect_fd ; //存放
            num ++;
        }

        //挨个儿轮询查看哪个客户端有发送信息过来(挨个儿通信)
        for(int i=0;i<=num;i++)
        {
            bzero(recv_msg,128); //清空缓冲区
            int byte =  recv(connect_addr[i], recv_msg , 128 , 0);

            if(byte>0)
            {
                printf("recive msg :%s",recv_msg);
            }
            
        }

    }
    
    //结束
    close(sockfd);


    return 0;
}
